package com.distribute.core.cachedata;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.distribute.core.core.BaseCacheManageCell;
import com.distribute.core.core.BaseNotifyMessage;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * GuavaLoadingCache缓存单元
 *
 * @author chennengcheng
 * @date 2021-01-15 11:27
 * @remark
 */
public abstract class BaseGuavaLoadingCacheCell<K , V> extends BaseCacheManageCell<BaseNotifyMessage> {

    private static final Logger log = LoggerFactory.getLogger(BaseGuavaLoadingCacheCell.class);
    /**
     * 本地缓存
     */
    public Cache<K , V> cache = CacheBuilder.newBuilder().build();

    @Override
    public String getCacheDataJson() {
        return JSONUtil.toJsonStr(cache);
    }

    @Override
    public int size() {
        return this.cache.asMap().size();
    }

    public V getValueByKey(@Nonnull K key, @Nonnull Supplier<V> getCacheByKeyFun) {
        if (getStatus().get()) {
            return cache.asMap().get(key);
        }

        return getCacheByKeyFun.get();
    }

    public Set<K> getAllKeys(@Nonnull Supplier<Set<K>> getAllKeysFun) {
        if (getStatus().get()) {
            return cache.asMap().keySet();
        }

        return getAllKeysFun.get();
    }

    public Collection<V> getAllValues(@Nonnull Supplier<Collection<V>> getAllValuesFun) {
        if (getStatus().get()) {
            return cache.asMap().values();
        }

        return getAllValuesFun.get();
    }

    public List<V> listValueByKeys(@Nonnull List<K> keys, @Nonnull Supplier<List<V>> listCacheByKeys) {
        if (CollectionUtil.isEmpty(keys)) {
            return new ArrayList<>();
        }

        if (getStatus().get()) {
            return keys.stream().filter(Objects::nonNull).map(key -> cache.asMap().get(key)).collect(Collectors.toList());
        }

        return listCacheByKeys.get();
    }

    public boolean containsKey(@Nonnull K key, @Nonnull Supplier<Boolean> containsKeyFun) {
        if (getStatus().get()) {
            return cache.asMap().containsKey(key);
        }

        return containsKeyFun.get();
    }

    public abstract int flushData(BaseNotifyMessage notifyMessage, Cache<K , V> cache);

    public abstract int flushAllData(Cache<K , V> cache);

    public abstract int initCacheData(Cache<K , V> cache);

    @Override
    protected int flush(BaseNotifyMessage notifyMessage) {
        return flushData(notifyMessage, cache);
    }

    @Override
    protected int flushAll() {
        return flushAllData(cache);
    }

    @Override
    public int initCache() {
        return initCacheData(cache);
    }

}
